﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ChessboardViewModel.cs" company="">
//   
// </copyright>
//  <summary>
//   The chessboard view model.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace Shatranj
{
    using System;
    using System.Collections.ObjectModel;
    using System.Threading;
    using System.Windows.Input;

    /// <summary>
    /// The chessboard view model.
    /// </summary>
    public class ChessboardViewModel : ViewModel
    {
        #region Fields

        /// <summary>
        /// The _board.
        /// </summary>
        private IChessboard _board;

        /// <summary>
        /// The board square view models.
        /// </summary>
        private ReadOnlyObservableCollection<BoardSquareViewModel> boardSquareViewModels;

        /// <summary>
        /// The has move begun.
        /// </summary>
        private bool hasMoveBegun;

        /// <summary>
        /// The piece selected handler.
        /// </summary>
        private ICommand pieceSelectedHandler;

        #endregion

        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="ChessboardViewModel"/> class.
        /// </summary>
        /// <param name="board">
        /// The board.
        /// </param>
        public ChessboardViewModel(IChessboard board)
        {
            this.Board = board;
            this.AsyncWireupViewModels();
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="ChessboardViewModel"/> class.
        /// </summary>
        public ChessboardViewModel()
            : this(new Chessboard())
        {
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets or sets the board.
        /// </summary>
        public IChessboard Board
        {
            get
            {
                return this._board;
            }

            set
            {
                this._board = value;
                this.RaisePropertyChanged("Board");
            }
        }

        /// <summary>
        /// Gets or sets the board square view models.
        /// </summary>
        public ReadOnlyObservableCollection<BoardSquareViewModel> BoardSquareViewModels
        {
            get
            {
                return this.boardSquareViewModels;
            }

            set
            {
                this.boardSquareViewModels = value;
                this.RaisePropertyChanged("BoardSquareViewModels");
            }
        }

        ////this is default when the board is created
        // private bool areWhitePiecesEnabled = true;
        // public bool AreWhitePiecesEnabled
        // {
        // get { return this.areWhitePiecesEnabled;}
        // set
        // {
        // this.areWhitePiecesEnabled = value;
        // RaisePropertyChanged("AreWhitePiecesEnabled");
        // }
        // }

        // private bool areBlackPiecesEnabled;
        // public bool AreBlackPiecesEnabled
        // {
        // get { return this.areBlackPiecesEnabled; }
        // set
        // {
        // this.areBlackPiecesEnabled = value;
        // RaisePropertyChanged("AreBlackPiecesEnabled");
        // }
        // }

        /// <summary>
        /// Gets or sets a value indicating whether has move begun.
        /// </summary>
        public bool HasMoveBegun
        {
            get
            {
                return this.hasMoveBegun;
            }

            set
            {
                this.hasMoveBegun = value;
                this.RaisePropertyChanged("HasMoveBegun");
            }
        }

        /// <summary>
        /// Gets or sets the piece selected handler.
        /// </summary>
        public ICommand PieceSelectedHandler
        {
            get
            {
                return this.pieceSelectedHandler;
            }

            set
            {
                this.pieceSelectedHandler = value;
                this.RaisePropertyChanged("PieceSelectedHandler");
            }
        }

        // TODO: Must be part of ViewModel
        /// <summary>
        /// Gets or sets a value indicating whether should animate.
        /// </summary>
        public bool ShouldAnimate { get; set; }

        #endregion

        #region Public Methods and Operators

        /// <summary>
        /// The piece selected.
        /// </summary>
        /// <param name="piece">
        /// The piece.
        /// </param>
        public void PieceSelected(ChessPiece piece)
        {
            this.Board.PrepareToMove(piece);
        }

        #endregion

        #region Methods

        /// <summary>
        /// The async wireup view models.
        /// </summary>
        private void AsyncWireupViewModels()
        {
            ThreadPool.QueueUserWorkItem(delegate { this.WireupViewModels(); });
            this.PieceSelectedHandler = new PieceSelectedCommand();

            // PieceSelectedHandler = new RoutedCommand("PieceSelected", this.GetType(), new InputGestureCollection() { new MouseGesture(MouseAction.LeftClick) });
        }

        /// <summary>
        /// The wireup view models.
        /// </summary>
        private void WireupViewModels()
        {
            var collection = new ObservableCollection<BoardSquareViewModel>();
            var boardTurn = Enum.GetName(typeof(Turn), this.Board.CurrentTurn);
            foreach (var square in this.Board.AllSquares)
            {
                var squareModel = new BoardSquareViewModel(square, this);
                collection.Add(squareModel);

                // var squareForce = squareModel.CurrentSquare.CurrentPiece == null?"None": 
                // Enum.GetName(typeof (Army), squareModel.CurrentSquare.CurrentPiece.Force);
                ////If the current square's force's turn, enable square
                // squareModel.IsEnabled = (squareForce == boardTurn);
            }

            this.BoardSquareViewModels = new ReadOnlyObservableCollection<BoardSquareViewModel>(collection);
        }

        #endregion

        /// <summary>
        /// The piece selected command.
        /// </summary>
        private class PieceSelectedCommand : ICommand
        {
            #region Public Events

            /// <summary>
            /// The can execute changed.
            /// </summary>
            public event EventHandler CanExecuteChanged;

            #endregion

            #region Public Methods and Operators

            /// <summary>
            /// The can execute.
            /// </summary>
            /// <param name="parameter">
            /// The parameter.
            /// </param>
            /// <returns>
            /// The <see cref="bool"/>.
            /// </returns>
            public bool CanExecute(object parameter)
            {
                if (parameter == null)
                {
                    return false;
                }

                var currentSquare = (parameter as BoardSquareViewModel).CurrentSquare;
                if (currentSquare == null)
                {
                    return false;
                }

                var squareForce = currentSquare.CurrentPiece == null
                                      ? "None"
                                      : Enum.GetName(typeof(Army), currentSquare.CurrentPiece.Force);

                // If the current square's force's turn, enable square
                return squareForce == Enum.GetName(typeof(Turn), currentSquare.Board.CurrentTurn);
            }

            /// <summary>
            /// The execute.
            /// </summary>
            /// <param name="parameter">
            /// The parameter.
            /// </param>
            public void Execute(object parameter)
            {
                // throw new NotImplementedException();
            }

            #endregion
        }
    }
}